<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/1/16
 * Time: 18:10
 */

namespace App\Process;


use App\Utility\HttpRequest;
use EasySwoole\Core\Component\Cache\Cache;
use EasySwoole\Core\Component\Di;
use EasySwoole\Core\Swoole\Process\AbstractProcess;
use EasySwoole\Core\Swoole\Time\Timer;
use Swoole\Process;
use EasySwoole\Config;
use App\Sock\Logic\Game as GameLogic;
use EasySwoole\Core\Swoole\ServerManager;

class GameTurn extends AbstractProcess
{

    protected $db;
    protected $timerId;
    protected $timerNId;
    protected $round_turn = 1;
    protected $start_time;
    protected $end_time;
    protected $round_time = 1 * 60;
    protected $open_time = 12;
    protected $curr_time;

    public function __construct(string $processName, array $args, bool $async = true)
    {
        $dbConf = Config::getInstance()->getConf('database');
        $this->db = Di::getInstance()->get('MYSQL');
        $this->db->setPrefix($dbConf['prefix']);
        $this->start_time = strtotime('10:00');
        $this->end_time = strtotime("01:55");
        $this->curr_time = time();
        parent::__construct($processName, $args, $async);
    }

    public function run(Process $process)
    {


        $current_time = $this->start_time;
        $current_end_time = $this->end_time;
//        if (time() > $current_end_time && time() < $current_time) {
//            Logger::getInstance()->console('当前时间不可进行游戏');
//
//        } else {
        // 创建当日第一局游戏或者重启后创建游戏

        // 查询最新一局游戏
        $left_time = $this->round_time;
        $this->db->where('year', date('Y'));
        $this->db->where('month', date('m'));
        $this->db->where('day', date('d'));
        $this->db->orderBy('round_id', 'desc');
        $result = $this->db->getOne('game_round');
        if (empty($result)) {
            $this->createFirstGameTurn();
        } else {
            $left_time = $result['end_time'] - time();
            $this->round_turn = $result['round_turn'] ?: '1';
        }

        if ($left_time > 0) {
            $this->runNew($left_time, true);
        } else {
            // 房间已经超时，重新创建

            $this->createFirstGameTurn(false);
            $this->runNew($this->round_time, false, $this->open_time);
        }
//        }
    }

    protected function createFirstGameTurn($is_first = true)
    {
        $room_list = Cache::getInstance()->get('room_list');
        if (!empty($room_list)) {
            foreach ($room_list as $item => $value) {
                $insert[] = [
                    'room_uuid' => $value['room_uuid'],
                    'round_uuid' => \App\Utility\UUID::v4(),
                    'start_time' => $this->curr_time,
                    'end_time' => ($this->curr_time + $this->round_time),
                    'year' => date('Y'),
                    'month' => date('m'),
                    'day' => date('d'),
                    'round_turn' => ($is_first ? 1 : $this->round_turn)
                ];

            }
            if (!$is_first) {
                $this->round_turn++;
            }

            if (!empty($insert)) {
                $rs = $this->db->insertMulti('game_round', $insert);

                if ($rs) {
                    $data['type'] = 'new_turn';
                    $data['content'] = [
                        'turn' => $this->round_turn,
                    ];
                    $this->sendMessage(['payload' => json_encode($data)]);
                }
                unset($insert);
            }
        }

    }

    protected function getOpenLottery()
    {
        $this->db->where('name', 'open_token');
        $list = $this->db->getOne('settings');
        $token = $list['value'] ?: 'teb6b9e68536f635fk';
        $url = "http://a.apiplus.net/{$token}/cqssc-1.json";
        $res = new HttpRequest();
        $result = $res->request('get', $url);
        $lottery_result = json_decode($result->getBody(), true);
        $number = $lottery_result['data'][0]['opencode'];
        return $number;
    }


    protected function handle()
    {
        $room_list = Cache::getInstance()->get('room_list');
        if (!empty($room_list)) {
            foreach ($room_list as $item => $value) {
                $this->db->where('room_uuid', $value['room_uuid']);
                $this->db->where('year', date('Y'));
                $this->db->where('month', date('m'));
                $this->db->where('day', date('d'));
                $this->db->orderBy('round_id', 'desc');
                $res = $this->db->getOne('game_round');
                if (!empty($res)) {
                    if (($res['end_time'] - time()) <= 0) {
                        $insert[] = [
                            'room_uuid' => $value['room_uuid'],
                            'round_uuid' => \App\Utility\UUID::v4(),
                            'start_time' => time(),
                            'end_time' => time() + $this->round_time,
                            'year' => date('Y'),
                            'month' => date('m'),
                            'day' => date('d'),
                            'round_turn' => $this->round_turn
                        ];
                    }
                } else {
                    $insert[] = [
                        'room_uuid' => $value['room_uuid'],
                        'round_uuid' => \App\Utility\UUID::v4(),
                        'start_time' => time(),
                        'end_time' => time() + $this->round_time,
                        'year' => date('Y'),
                        'month' => date('m'),
                        'day' => date('d'),
                        'round_turn' => $this->round_turn
                    ];

                }
            }
            if (!empty($insert)) {
                $rs = $this->db->insertMulti('game_round', $insert);
                if ($rs) {
                    $data['type'] = 'new_turn';
                    $data['content'] = [
                        'turn' => $this->round_turn,
                        'left_time' => $this->round_time -5,
                    ];
                    $this->sendMessage(['payload' => json_encode($data)]);
                }
            }
        }

    }

    protected function runNew($time = 60 * 5, $is_left = false, $open_time = 60, $isbreak = false)
    {

        $s_t = microtime(true);

        echo 'input_time:' . $time . PHP_EOL;


        if ($is_left) {
            echo 'input_time_left:' . $time . PHP_EOL;
            Timer::delay($time * 1000 + 6000, function () use ($time, $open_time) {
//                sleep($open_time);
                $this->round_turn++;
                $this->handle();

                $this->runNew($this->round_time, false, $this->open_time, true);
            });
            Timer::delay(($time - 8) * 1000, function () {
                $result = $this->getOpenLottery();
                if (strpos($result, ',') !== FALSE) {

                    $this->db->where('round_turn', $this->round_turn);
                    $this->db->where('year', date('Y'));
                    $this->db->where('month', date('m'));
                    $this->db->where('day', date('d'));
                    $update = [
                        'round_result' => $result
                    ];
                    $this->db->update('game_round', $update);
                    $nums = explode(',', $result);

                    $num['code'] = $nums;
                    $data['type'] = 'open_lottery';
                    $data['content'] = [
                        'turn' => $this->round_turn,

                        'code' => $nums
                    ];
                    $this->sendMessage(['payload' => json_encode($data)]);
                }


            });
            Timer::delay(($time - 5) * 1000, function () {
                $this->openLottery();
            });


        } else {
            $this->timerId = Timer::loop($this->round_time * 1000  , function () use ($time, $s_t) {
                echo 'input_time_timer:' . $time . PHP_EOL;


//                $e_t = microtime(true);
//                echo PHP_EOL . "_______________________________________" . PHP_EOL;
//                echo $this->round_turn;
//
//                echo PHP_EOL . "---------------------------------------" . PHP_EOL;
//                echo $e_t - $s_t . PHP_EOL;
//                echo PHP_EOL . "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" . PHP_EOL;


                $result = $this->getOpenLottery();
                if (strpos($result, ',') !== FALSE) {

                    $this->db->where('round_turn', $this->round_turn);
                    $this->db->where('year', date('Y'));
                    $this->db->where('month', date('m'));
                    $this->db->where('day', date('d'));
                    $update = [
                        'round_result' => $result
                    ];
                    $this->db->update('game_round', $update);
                    $nums = explode(',', $result);

                    $num['code'] = $nums;
                    $data['type'] = 'open_lottery';
                    $data['content'] = [
                        'turn' => $this->round_turn,
                        'code' => $nums
                    ];
                    $this->sendMessage(['payload' => json_encode($data)]);
                }


                //所有房间



                $this->openLottery();
                $this->round_turn++;


                sleep(16);
                $this->handle();



            });
        }
    }

    public function openLottery()
    {
        $this->db->where('round_turn', $this->round_turn-1);
        $bet_log = $this->db->get('bet_log');

        $rate = Cache::getInstance()->get('rate');


        foreach ($bet_log as $item => $value) {
            $this->db->where('round_turn', $this->round_turn - 1);
            $this->db->where('round_uuid', $value['round_uuid']);
            $this->db->where('room_uuid', $value['room_uuid']);
            $result = $this->db->getOne('game_round');
            $lottery = \App\Utility\MTool::handle_number($result['round_result']);
            if ($value['bet_type'] != 'two_star') {
                if ($lottery[$value['bet_info']]) {
                    if (in_array($value['bet_type'], $lottery[$value['bet_info']]['type'])) {
                        // 更新开奖结果
                        $this->db->where('bl_id', $value['bl_id']);
                        $get_coin = bcmul($value['bet_amount'], $rate[$value['bet_type'] . '_rate']);
                        $update = ['bet_result' => 1, 'bet_res_amount' => $get_coin];
                        $this->db->update('bet_log', $update);
                        // 更新用户金币

                        $update_user = [
                            'coin' => $this->db->inc($get_coin),
                        ];
                        $this->db->where('id', $value['user_id']);
                        $this->db->update('user', $update_user);

                    } else {
                        $this->db->where('bl_id', $value['bl_id']);
                        $update = ['bet_result' => 2];
                        $this->db->update('bet_log', $update);
                    }
                }
            } else {
                $bet_data = explode(',', $value['bet_data']);
                $in_arr[0] = $lottery[$bet_data[0]]['value'];
                $in_arr[1] = $lottery[$bet_data[1]]['value'];
                $open_num = implode(',', $in_arr);
                if ($value['bet_info'] == $open_num) {
                    // 更新开奖结果
                    $this->db->where('bl_id', $value['bl_id']);
                    $get_coin = bcmul($value['bet_amount'], $rate[$value['bet_type'] . '_rate']);
                    $update = ['bet_result' => 1, 'bet_res_amount' => $get_coin];
                    $this->db->update('bet_log', $update);
                    // 更新用户金币

                    $update_user = [
                        'coin' => $this->db->inc($get_coin),
                    ];
                    $this->db->where('id', $value['user_id']);

                    $this->db->update('user', $update_user);


                } else {
                    $this->db->where('bl_id', $value['bl_id']);
                    $update = ['bet_result' => 2];
                    $this->db->update('bet_log', $update);

                }
            }
        }


    }

//当进程关闭的时候会执行该事件
    public
    function onShutDown()
    {
        // TODO: Implement onShutDown() method.
    }


    protected
    function sendMessage($taskData = [])
    {
        $users = [];
        $roomid = isset($taskData['room_id']) ? $taskData['room_id'] : 0;
        if (empty($roomid)) {
//            $users = Game::
            //获取所有RoomUUID
            $room_list = Cache::getInstance()->get('room_list');
            foreach ($room_list as $item => $value) {
                $user[] = GameLogic::selectRoomFd($value['room_uuid']);
            }
            if (!empty($user)) {
                if (count($user) == 1) {
                    $users = $user[0];
                } else {
                    $users = [];
                    foreach ($user as $items => $list) {
                        foreach ($list as $ii => $vv) {
                            $users[] = $vv;
                        }
                    }
                }
            }


        } else {
            $users = GameLogic::selectRoomFd($roomid);
        }

        /** @var \swoole_websocket_server $server */
        $server = ServerManager::getInstance()->getServer();
        foreach ($users as $userFd) {
            $connection = $server->connection_info($userFd);
            if ($connection['websocket_status'] == 3) { // 用户正常在线时可以进行消息推送
                $server->push($userFd, $taskData['payload']);
            }
        }
    }

//当有信息发给该进程的时候，会执行此进程
    public
    function onReceive(string $str, ...$args)
    {
        if ($str == 'start') {
            $this->runNew($this->round_time);
        }
        if ($str == 'stop') {
            $this->round_turn = 1;
            Timer::clear($this->timerId);
        }
        // TODO: Implement onReceive() method.
//        var_dump('process rec' . $str);
    }

}